/* 
 * BAT_Annotation.h
 *
 * Data structures for BAT_GeneTab formatted files.
 *
 * $Id: BAT_Annotation.h 927 2006-09-03 06:17:24Z rpz $
 *
 * Bob Zimmermann <rpz@cse.wustl.edu>
 * Totally free.
 *
 */

#ifndef BAT_H
#  define BAT_H

#  include "darray.h"
#  include "keyed_set.h"
#  include <stdio.h>
#  include <string.h>
#include <stdarg.h>

/* forward decls */
typedef struct _BAT_GeneTab BAT_GeneTab;
typedef struct _BAT_Gene BAT_Gene;
typedef struct _BAT_Transcript BAT_Transcript;
typedef struct _BAT_Feature BAT_Feature;
typedef struct _BAT_Free_Feature BAT_Free_Feature;
typedef struct _BAT_Comment BAT_Comment;
typedef struct _BAT_Attribute BAT_Attribute;

typedef struct _BAT_Base BAT_Base;

typedef struct _BAT_State BAT_State;

typedef int (*BAT_GeneTab_cmpF) (const void *, const void *);

typedef unsigned long BAT_Coord;

typedef enum _BAT_Strand
{ PLUS = 0, MINUS, STRAND } BAT_Strand;

typedef enum _BAT_Allocator_ID
{
  Gene_Allocator = 0,
  Transcript_Allocator,
  Feature_Allocator,
  Free_Feature_Allocator,
  Attribute_Allocator,
  Line_Allocator,
  Null_Allocator
} BAT_Allocator_ID;

typedef enum _BAT_Feature_Type
{
  CDS = 0,
  UTR5,
  UTR3,
  start_codon,
  stop_codon,
  inter,
  inter_CNS,
  intron_CNS,
  exon,
  FEATURE_TYPE
} BAT_Feature_Type;

typedef enum _BAT_Object_Type
{
  BAT_GTF_Obj,
  BAT_Gene_Obj,
  BAT_Transcript_Obj,
  BAT_Feature_Obj,
  BAT_Free_Feature_Obj,
  BAT_Attribute_Obj
} BAT_Object_Type;

struct _BAT_State
{
  int mod_gene_id:1;		/* a parent modified the gene_id, must change attr */
  int mod_transcript_id:1;
  int mod_genes:1;		/* resize gene allocator, nothing out of order */
  int mod_transcripts:1;	/* and so forth ... */
  int mod_features:1;
  int mod_attributes:1;
  int add_genes:1;		/* added an gene to gene allocator out of order */
  int add_transcripts:1;
  int add_features:1;
};

struct _BAT_Base
{
  BAT_Base *_parent;
  darray_t *_children;
  keyed_set_t *_allocators;
  BAT_State _state;
};

struct _BAT_Attribute
{
  char *key;
  char *value;
};

struct _BAT_Comment
{
  darray_t *lines;

  int offset;			/* the offset from the last character in the
				 * line */
  char *inltext;
};

struct _BAT_Feature
{
  BAT_Transcript *_parent;
  darray_t *attributes;

  BAT_Comment *comment;
  BAT_Coord start;
  BAT_Coord end;
  int score;
  int frame:2;
  int type:5;
};

struct _BAT_Free_Feature
{
  void *_parent; /* unused */
  darray_t *attributes;

  BAT_Comment *comment;
  BAT_Coord start;
  BAT_Coord end;
  int score;
  int frame:2;
  int type:5;
  int strand:2;
  char *seqname;
  char *source;
};

struct _BAT_Transcript
{
  BAT_Gene *_parent;
  darray_t *_children;
  keyed_set_t *_allocators;
  BAT_State _state;

  char *id;
  BAT_Coord min;
  BAT_Coord max;
};

struct _BAT_Gene
{
  BAT_GeneTab *_parent;
  darray_t *_children;
  keyed_set_t *_allocators;
  BAT_State _state;

  char *seqname;
  char *source;
  BAT_Strand strand;
  char *id;

  BAT_Coord min;
  BAT_Coord max;
};

struct _BAT_GeneTab
{
  void *_parent;
  darray_t *_children;
  keyed_set_t *_allocators;
  BAT_State _state;
};

/* FIXME: These are here because bat_private functions are used in
 * BAT_GTF_Writer.c, and should not be.  when you double include BAT_Private,
 * which has a lot of global decls, you get trouble. */


BAT_GeneTab *BAT_GeneTab_new ();
BAT_GeneTab *BAT_GeneTab_copy (BAT_GeneTab * bat);
void BAT_GeneTab_delete (BAT_GeneTab * , int);
void BAT_GeneTab_insert_gene (BAT_GeneTab * bat, BAT_Gene * gene);
void BAT_GeneTab_add_gene (BAT_GeneTab * bat, BAT_Gene * gene);
BAT_Gene * BAT_GeneTab_remove_gene (BAT_GeneTab * bat, BAT_Gene * gene, int befrei);
BAT_Gene **BAT_GeneTab_get_genes (BAT_GeneTab * bat, da_pos_t *n_genes);
BAT_Gene *BAT_GeneTab_find_gene (BAT_GeneTab * bat, const char *id);
BAT_Transcript **BAT_GeneTab_get_transcripts (BAT_GeneTab * bat,
					      da_pos_t *n_transcripts);
BAT_Transcript *BAT_GeneTab_find_transcript (BAT_GeneTab * bat,
					     const char *id);
BAT_Feature **BAT_GeneTab_get_features (BAT_GeneTab * bat, da_pos_t *n_features);

BAT_Gene *BAT_Gene_new ();
BAT_Gene *BAT_Gene_copy (BAT_Gene * gene);
void BAT_Gene_delete (BAT_Gene * gene, int);
void BAT_Gene_set_all (BAT_Gene * gene, const char *seqname,
		       const char *source, BAT_Strand strand, const char *id);
void BAT_Gene_set_id (BAT_Gene * gene, const char *id);
void BAT_Gene_set_seqname (BAT_Gene * gene, const char *seqname);
void BAT_Gene_set_source (BAT_Gene * gene, const char *source);
void BAT_Gene_set_strand (BAT_Gene * gene, BAT_Strand strand);
BAT_Coord BAT_Gene_get_min (BAT_Gene * gene);
BAT_Coord BAT_Gene_get_max (BAT_Gene * gene);
void BAT_Gene_insert_transcript (BAT_Gene * gene, BAT_Transcript * tx);
void BAT_Gene_add_transcript (BAT_Gene * gene, BAT_Transcript * tx);
BAT_Transcript * BAT_Gene_remove_transcript (BAT_Gene * gene, BAT_Transcript * tx, int befrei);
BAT_Transcript **BAT_Gene_get_transcripts (BAT_Gene * gene,
					   da_pos_t *n_transcripts);
BAT_Feature **BAT_Gene_get_features (BAT_Gene * gene, da_pos_t *n_features);
int BAT_Gene_order (const void **f1, const void **f2);
int BAT_Gene_cmp (const BAT_Gene * gene, const BAT_Gene * cmp);
int BAT_Gene_id_cmp (const void *gene, const void *id);


BAT_Transcript *BAT_Transcript_new ();
BAT_Transcript *BAT_Transcript_copy (BAT_Transcript * transcript);
void BAT_Transcript_delete (BAT_Transcript * tx, int);
void BAT_Transcript_insert_feature (BAT_Transcript * tx, BAT_Feature * feat);
void BAT_Transcript_add_feature (BAT_Transcript * tx, BAT_Feature * feat);
BAT_Feature * BAT_Transcript_remove_feature (BAT_Transcript * tx, BAT_Feature * feat, int);
BAT_Feature **BAT_Transcript_get_features (BAT_Transcript * tx,
					   da_pos_t *n_features);
char *BAT_Transcript_get_gene_id (BAT_Transcript * tx);
void BAT_Transcript_set_id (BAT_Transcript * tx, const char *id);
BAT_Coord BAT_Transcript_get_min (BAT_Transcript * tx);
BAT_Coord BAT_Transcript_get_max (BAT_Transcript * tx);

BAT_Feature_Type BAT_Feature_Type_from_str (const char *str);
char *BAT_Feature_Type_get_str (BAT_Feature_Type ft);

char BAT_Strand_get_strand_char (BAT_Strand s);


BAT_Feature *BAT_Feature_new ();
BAT_Feature *BAT_Feature_copy (BAT_Feature * feat);
void BAT_Feature_delete (BAT_Feature * , int);
void BAT_Feature_set_all(BAT_Feature * feat, BAT_Feature_Type type,
        BAT_Coord start, BAT_Coord end, int score, int frame);
void BAT_Feature_set_comment (BAT_Feature * feat, BAT_Comment * cmt);
void BAT_Feature_set_seqname (BAT_Feature * feat, const char *seqname);
void BAT_Feature_set_source (BAT_Feature * feat, const char *source);
void BAT_Feature_set_frame (BAT_Feature * feat, int frame);
void BAT_Feature_set_feature_type (BAT_Feature * feat, BAT_Feature_Type type);
void BAT_Feature_set_type(BAT_Feature * feat, BAT_Feature_Type type);
void BAT_Feature_set_start (BAT_Feature * feat, BAT_Coord start);
void BAT_Feature_set_end (BAT_Feature * feat, BAT_Coord end);
void BAT_Feature_set_score (BAT_Feature * feat, int score);
void BAT_Feature_set_attribute (BAT_Feature * feat, BAT_Attribute * attr);
void BAT_Feature_set_attribute_by_keyvalue (BAT_Feature * feat, const char *,
					    const char *);
char *BAT_Feature_get_gene_id (BAT_Feature *);
char *BAT_Feature_get_transcript_id (BAT_Feature *);
BAT_Strand BAT_Feature_get_strand(const BAT_Feature *);
char *BAT_Feature_get_seqname(BAT_Feature *);
char * BAT_Feature_get_source(BAT_Feature *);
BAT_Attribute * BAT_Feature_remove_attribute (BAT_Feature * feat, BAT_Attribute * attr, int);
BAT_Attribute *BAT_Feature_find_attribute (BAT_Feature * feat,
					   const char *key);
BAT_Attribute **BAT_Feature_get_attributes (BAT_Feature * feat, da_pos_t *size);
char BAT_Feature_get_frame_char (BAT_Feature * feat);
int BAT_Feature_order (const void **f1, const void **f2);
int BAT_Feature_cmp (const BAT_Feature * gene, const BAT_Feature * cmp);
int BAT_Feature_gid_cmp (const void **f1, const void **f2);
int BAT_Feature_tid_cmp (const void **f1, const void **f2);

BAT_Free_Feature *BAT_Free_Feature_new ();
BAT_Free_Feature *BAT_Free_Feature_copy (BAT_Free_Feature * feat);
void BAT_Free_Feature_delete (BAT_Free_Feature * , int);
void BAT_Free_Feature_set_all(BAT_Free_Feature * , BAT_Feature_Type ,
        BAT_Coord , BAT_Coord , int , int , BAT_Strand , const char *, const char *);
void BAT_Free_Feature_set_comment (BAT_Free_Feature * feat, BAT_Comment * cmt);
void BAT_Free_Feature_set_seqname (BAT_Free_Feature * feat, const char *seqname);
void BAT_Free_Feature_set_source (BAT_Free_Feature * feat, const char *source);
void BAT_Free_Feature_set_transcript_id (BAT_Free_Feature * feat,
				    const char *transcript_id);
void BAT_Free_Feature_set_gene_id (BAT_Free_Feature * feat, const char *gene_id);
void BAT_Free_Feature_set_frame (BAT_Free_Feature * feat, int frame);
void BAT_Free_Feature_set_feature_type (BAT_Free_Feature * feat, BAT_Feature_Type type);
void BAT_Free_Feature_set_strand (BAT_Free_Feature * feat, BAT_Strand strand);
void BAT_Free_Feature_set_start (BAT_Free_Feature * feat, BAT_Coord start);
void BAT_Free_Feature_set_end (BAT_Free_Feature * feat, BAT_Coord end);
void BAT_Free_Feature_set_score (BAT_Free_Feature * feat, int score);
void BAT_Free_Feature_set_attribute (BAT_Free_Feature * feat, BAT_Attribute * attr);
void BAT_Free_Feature_set_attribute_by_keyvalue (BAT_Free_Feature * feat, const char *,
					    const char *);
char *BAT_Free_Feature_get_gene_id (BAT_Free_Feature *);
char *BAT_Free_Feature_get_transcript_id (BAT_Free_Feature *);
BAT_Attribute * BAT_Free_Feature_remove_attribute (BAT_Free_Feature * feat, BAT_Attribute * attr, int);
BAT_Attribute *BAT_Free_Feature_find_attribute (BAT_Free_Feature * feat,
					   const char *key);
BAT_Attribute **BAT_Free_Feature_get_attributes (BAT_Free_Feature * feat, da_pos_t *size);
char BAT_Free_Feature_get_frame_char (BAT_Free_Feature * feat);
int BAT_Free_Feature_order (const void **f1, const void **f2);
int BAT_Free_Feature_cmp (const BAT_Free_Feature * gene, const BAT_Free_Feature * cmp);
int BAT_Free_Feature_gid_cmp (const void **f1, const void **f2);
int BAT_Free_Feature_tid_cmp (const void **f1, const void **f2);



BAT_Comment *BAT_Comment_new ();
BAT_Comment *BAT_Comment_copy (BAT_Comment * cmt);
void BAT_Comment_delete (BAT_Comment * cmt, int);
void BAT_Comment_set_offset (BAT_Comment * cmt, int ofs);
void BAT_Comment_set_inline_text (BAT_Comment * cmt, const char *text);
void BAT_Comment_add_line (BAT_Comment * cmt, const char *line);
int BAT_Transcript_order (const void **f1, const void **f2);
int BAT_Transcript_cmp (const BAT_Transcript * gene,
			const BAT_Transcript * cmp);
int BAT_Transcript_id_cmp (const void *gene, const void *id);

BAT_Attribute *BAT_Attribute_new ();
BAT_Attribute *BAT_Attribute_new_gene_id ();
BAT_Attribute *BAT_Attribute_new_transcript_id ();
BAT_Attribute *BAT_Attribute_copy (BAT_Attribute * attr);
void BAT_Attribute_delete (BAT_Attribute * attr, int);
void BAT_Attribute_set_all (BAT_Attribute * attr, const char *key,
			    const char *value);
void BAT_Attribute_set_key (BAT_Attribute * attr, const char *key);
void BAT_Attribute_set_value (BAT_Attribute * attr, const char *value);
int BAT_Attribute_order (const void **f1, const void **f2);
int BAT_Attribute_key_cmp (const void *attr, const void *id);

char *BAT_Util_copy_string(const char *s);
char *BAT_Util_copy_char(const char *s);
void BAT_Util_free(void *, int);

/* 
 * These operations are for the direct children of every node in the 
 * annotation tree.  Since the parents own them, they clean up allocated
 * memory.  The passive operations contain all operations except the
 * copy and delete operatiions: they don't allocate or delete.
 */
extern darray_ops_t BAT_Owner_Ops[];
extern darray_ops_t BAT_Passive_Ops[];
extern keyed_set_ops_t BAT_KS_Ops;

#endif /* BAT_H */
